package cn.biplam.front.template.control;

import java.util.ArrayList;

import cn.biplam.common.client.OperatorResult;
import cn.biplam.common.client.Paging;
import cn.biplam.common.tools.TOOLS;
import cn.biplam.common.wrapper.ErrorMessage;
import cn.biplam.common.wrapper.KvMap;
import cn.biplam.common.wrapper.Result;
import cn.biplam.front.callback.CallBack;
import cn.biplam.front.component.data.common.PagingComp;
import cn.biplam.front.html.HtmlDiv;
import cn.biplam.front.html.HtmlValue;
import cn.biplam.front.html.base.Html;
import cn.biplam.front.html.base.HtmlWindow;
import cn.biplam.front.html.base.Const.Length_Unit;
import cn.biplam.front.html.base.Const.Position_Mode;
import cn.biplam.front.html.base.Const.Window_Event;
import cn.biplam.front.htmlscript.script.FlowTableScript;
import cn.biplam.front.template.Template;
import cn.biplam.front.template.base.HiddenParam;
import cn.biplam.front.template.control.table.ElementID;
import cn.biplam.front.template.control.table.Table;
import cn.biplam.front.template.control.table.TablePropertys;
import cn.biplam.front.template.control.table.TableScript;
import cn.biplam.front.template.control.table.cell.AnchorCell;
import cn.biplam.front.template.control.table.cell.ButtonCell;
import cn.biplam.front.template.control.table.cell.Cell;
import cn.biplam.front.template.control.table.cell.CheckBoxCell;
import cn.biplam.front.template.control.table.cell.InputCell;
import cn.biplam.front.template.control.table.cell.RadioCell;
import cn.biplam.front.template.control.table.cell.TextCell;
import cn.biplam.front.template.control.table.cell.ThCell;

/**
 * 流式表格 
 * <ul>功能：
 * <li>表格与数据集绑定 
 * <li>表格的每行显示数据集的一行
 * <li>表格与数据集绑定后自动布局返回表格界面
 * <li>表格列宽度由预先定义的表格列类型和单元格数据内容得出
 * <li>当单元格格内容为外部html对象时,根据传入绑定器创建单元格
 * </ul> 
 * <ul>用法：
 * <li> new FlowTable("表格页面ID","数据集主键名称","表格属性绑定器") 创建表格 
 * <li> this.put("数据集")                                      绑定数据集到表格
 * <li> 通过 setWidth(value) setHeight(value) 设置表格宽度和高度
 * <li> this.get()                                             获取表格
 * </ul>  
 * @author XiaoRuxing 2009-5-24下午04:46:21
 * @version 1.0
 */
public class FlowTable implements Template{

	/** 内容 */
	private Table table;
	/** 表内容区域ID */
	private String tableId;
	/** 表主键 */
	private String mainKey;
	/** 表属性 */
	private final TablePropertys propertys;

	/** 表格内容所占高度 */
	private double height=0;
	/** 表格内容所占宽度 */
	private int width=0;
	/** 表占位宽度 */
	private String clientWidth=null;
	/** 表占位高度 */
	private String clientHeight=null;
	/** 每列最大宽度 */
	private int[] maxColWidth;
	/** 当前行记录ID*/
	private String keyValue = null;

	/** 表格记录集 */
	private OperatorResult result;
	private Result data;
	/** 外部设置宽度 */
	private String sOutWidth;
	/** 外部设置高度 */
	private String sOutHeight;

	/** 当前表格显示模式(默认单页显示模式) */
	private Flow_Table_View_Model viewModel = Flow_Table_View_Model.Single_Page;
	/** 分页模版对象 */
	private PagingComp pageComp = null; 
	/** 数据集分页信息 */
	private Paging pageInfo = null;
	/** 表格对应的记录ID  */
	private String tablePageRecord = null;
	/** 分页对象高度 */
	private int pageCompHeight = 0;

	/** 表格附加对象 */
	private ArrayList<Html> addElements;

	/** 表格绑定数据集为空时的提示信息 */
	private String emptyInfo = "&nbsp;";

	/** 存放行刷新动作ID容器的页面ID */
	private static String refreshAidCont="_refAidCon";
	/** 行刷新动作ID */
	private String refreshAid;

	/** 存储列内容,列名为键,用于需要剔重显示列 */
	private KvMap<String, String> colContent;

	/** 每行高度(Px) */
	private static final double PER_ROW_HEIGHT = 25;
	/** 标题行高度 */
	private static final double TITLE_ROW_HEIGHT = 22;

	/**
	 * 流式布局表显示模式
	 */
	public enum Flow_Table_View_Model{
		/** 分页模式 */
		Multi_Page,
		/** 单页显示模式 */
		Single_Page
	}

	/**
	 * 传入表格页面ID,数据集主键名称和表格属性创建流式布局表格
	 * @param tableId   表格页面ID
	 * @param mainKey   数据集主键名称
	 * @param propertys 表格属性
	 */
	public FlowTable(String tableId,String mainKey,TablePropertys propertys) throws ErrorMessage{
		this(tableId, mainKey, propertys, null);
	}

	/**
	 * 传入表格页面ID,数据集主键名称和表格属性创建流式布局表格
	 * @param tableId    表格页面ID
	 * @param mainKey    数据集主键名称
	 * @param propertys  表格属性
	 * @param recordId   表格记录ID
	 */
	public FlowTable(String tableId,String mainKey,
			TablePropertys propertys,
			String recordId) throws ErrorMessage{
		this.tableId=tableId;
		this.propertys=propertys;
		this.mainKey=mainKey;
		this.addElements = new ArrayList<Html>();
		this.colContent = new KvMap<String, String>();
	}

	/**
	 * 放入数据集数据到table
	 * @param data 表数据，数据格式为含有列索引的二维表
	 * @throws ErrorMessage 
	 */
	public void put(OperatorResult result) throws ErrorMessage{
		this.result=result;
	}

	/**
	 * 设置表格占位宽度,如果表格的占位宽度大于实际宽度则实际宽度等于占位宽度
	 * @param value 值
	 * @throws ErrorMessage
	 */
	public void setWidth(String value) throws ErrorMessage{
		this.sOutWidth = value;
	}

	/**
	 * 设置表格占位高度
	 * @param value 值
	 * @throws ErrorMessage
	 */
	public void setHeight(String value) throws ErrorMessage{
		this.sOutHeight = value;
	}

	/**
	 * 放入非行列的额外隐藏对象
	 * @param html
	 * @throws ErrorMessage 
	 */
	public void putExtend(Html html) throws ErrorMessage{
		this.addElements.add(html);
	}

	/**
	 * 设置表格分页参数(要刷新的目标区域ID就是当前表格)
	 * @param pageActID  分页跳转动作ID
	 * @param recordId   分页页面记录ID
	 */
	public void setPageProperty(String pageActID, String recordId){
		this.setPageProperty(pageActID, recordId,tableId);
	}

	/**
	 * 设置表格分页参数(要刷新的目标区域不是当前表格)
	 * @param pageActID  分页跳转动作ID
	 * @param recordId   分页页面记录ID
	 * @param targID     要刷新的目标区域ID
	 */
	public void setPageProperty(String pageActID, String recordId, String targID){
		this.pageComp = new PagingComp(this.tableId,pageActID,targID);
		this.tablePageRecord = recordId;
		this.pageCompHeight = pageComp.getHeight();
	}

	/**
	 *  设置行刷新动作ID
	 * @param refAid 行刷新动作ID
	 */
	public void setRowRefreshAid(String refAid){
		this.refreshAid = refAid;
	}

	/**
	 *  设置记录集为空时表格显示信息
	 * @param emptyInfo 空提示信息
	 */
	public void setEmptyTitle(String emptyInfo){
		this.emptyInfo = emptyInfo;
	}

	/**
	 * 获取表格页面ID
	 * @return 表格页面ID
	 */
	public String getID(){
		return this.tableId;
	}

	/**
	 * 获取表格实际内容宽度,在调用get()之后才能获取表格宽度
	 * @return
	 */
	public String getWidth(){
		return TOOLS.intToString(this.width+17);
	}

	/**
	 * 获取表格实际内容高度,在调用get()之后才能获取表格高度
	 * @return
	 */
	public String getHeight(){
		return TOOLS.intToString((int)this.height+17);
	}

	/**
	 * 获取表格
	 * @return
	 * @throws ErrorMessage 
	 */
	public HtmlWindow get() throws ErrorMessage{
		_init();
		//如果是分页模式插入分页控件
		if(this.viewModel.equals(Flow_Table_View_Model.Multi_Page)
				&& pageComp!=null){
			pageComp.setWidth(TOOLS.intToString(width));
			table.putExtend(pageComp.get(propertys.getUser(), propertys.getSHomeUrl(), this.pageInfo,this.tablePageRecord));
		}

		//设置表格容器的大小
		if(clientHeight!=null){
			table.setClientHeight(clientHeight);
		}else if(this.viewModel.equals(Flow_Table_View_Model.Multi_Page)){
			table.setClientHeight(TOOLS.intToString((int)this.height+this.pageCompHeight));
		}else{
			table.setClientHeight(TOOLS.intToString((int)this.height));
		}

		this.table.setStyle("border-top", "0");
		HtmlWindow tb=table.get();
		HtmlWindow title = table.getRow(0);
		_setStyle(tb);
		_setTitleStyle(title);
		tb.bind(FlowTableScript.flowTableResize(tableId));
		return tb;
	}

	/**
	 * 初始化表格
	 */
	private void _init() throws ErrorMessage{
		//创建表格
		this.table=new Table(tableId);
		//初始化每列最大宽度
		this.maxColWidth=new int[propertys.getColNumber()];
		//初始化表标题行
		_initTitle();
		//绑定数据到表格
		_putData();
		//设置是否分页
		this._setPageProperty();
		//根据外部传入表格宽度和高度计算表格大小
		this._setSize();
		//根据外部传入大小和表格实际内容计算表格每列宽度
		this._generatorTableWidth();
		//放入附加元素
		_setAddElements();
		//设置表格行刷新动作
		this._setRefreshAct();
	}

	/**
	 *  设置表格显示样式
	 * @throws ErrorMessage 
	 */
	private void _setStyle(HtmlWindow tb) throws ErrorMessage{
		tb.setStyle("overflow-y", "scroll");
		tb.setStyle("overflow-x", "auto");
	}

	/**
	 *  设置标题行样式
	 * @throws ErrorMessage 
	 */
	private void _setTitleStyle(HtmlWindow title) throws ErrorMessage{
		title.setPositionMode(Position_Mode.Relative);
		title.setTop("expression(this.offsetParent.scrollTop)",Length_Unit.empty);
	}

	/**
	 *  设置表格行刷新动作ID
	 * @throws ErrorMessage 
	 */
	private void _setRefreshAct() throws ErrorMessage{
		HiddenParam hp = new HiddenParam(this.tableId+refreshAidCont,this.refreshAid);
		this.table.putExtend(hp.get());
	}

	/**
	 *  绑定数据到表格
	 * @throws ErrorMessage 
	 */
	private void _putData() throws ErrorMessage{
		//如果传入数据集为空,插入空行
		if(!TOOLS.exist(result))this.putNull();
		this.data = result.getResult();
		/** 列名称 */
		String colName=null;
		/** 行ID */
		String rowID=null;
		/** 主键值 */
		String keyValue=null;
		int rowIndex;//行
		while(data.next()){
			//当前行下标
			rowIndex=data.getCurrentRow()+1;
			//生成当前行ID
			rowID=new ElementID(tableId,rowIndex).toString();
			//生成行数据
			for(int j=0;j<propertys.getColNumber();j++){
				/** 将主键值对应的隐藏input放入第一列 */
				colName=propertys.getColName(j);
				if(j==0){
					keyValue=data.getString(mainKey);
					this.keyValue = keyValue;
				}else{
					keyValue=null;
				}
				//获取当前列数据,插入到表格
				if(!propertys.isExtent(colName)){//插入数据源为外部传入的对象
					put(rowIndex,j,data.getString(colName),keyValue,rowID);
				}else{//插入数据源为数据集内容的单元格
					put(rowIndex,j,colName,keyValue,rowID);
				}
			}
			_getTableHeight();//计算当前表格高度
		}
		_getTableWidth();//计算当前表格宽度
	}

	/**
	 *  当前表格传入数据集为空时插入空行
	 * @throws ErrorMessage
	 */
	private void putNull() throws ErrorMessage{
		table.put(
				new HtmlDiv(null,null,this.emptyInfo),
				1,
				TOOLS.intToString(propertys.getColNumber()));
		_getTableHeight();
	}

	/**
	 * 根据列类型及传入单元格内容创建单元格，插入表
	 * @param row   行
	 * @param col   列 
	 * @param content 参数
	 * @throws ErrorMessage 
	 */
	private void put(int row,int col,String content,String keyValue,String rowID) throws ErrorMessage{
		/** 单元格对象 */
		HtmlWindow tableCell=null;
		/** 获取单元格对象 */
		if(propertys.isExtent(col)){
			tableCell=_getExtentTableCell(row, col, rowID);
		}else{
			tableCell=_getTableCell(col, content,rowID);
		}
		/** 如果是第一列插入主键值隐藏对象 */
		if(keyValue!=null){
			tableCell.put(_getRowHiddenKey(rowID, keyValue));
		}
		/** 将单元格放入表格 */
		this.table.put(tableCell,row);
	}

	/**
	 * 根据单元格内容和单元格类型生成单元格控件
	 * @param row      行
	 * @param col      列
	 * @param content  内容
	 * @return
	 * @throws ErrorMessage
	 */
	private HtmlWindow _getTableCell(int col,String content,String rowID) throws ErrorMessage{

		HtmlWindow tableCell=null;
		String colName=propertys.getColName(col);//获取当前列名
		content = _disContent(content, colName);//设置需要剔重列列内容,列数据源为数据集数据时有效
		Cell cell=null;

		/**2 根据字段类型创建表格单元格对象，放入单元格 */
		switch (propertys.getTableColType(col)) {
		case NAME_TEXT: 
			cell=new TextCell(content,tableId);
			break;
		case NAME_ANCHOR:
			cell=new AnchorCell(content,tableId);
			break;
		case DESC_SHORT_TEXT:
			cell=new TextCell(null,content,TablePropertys.sShortDescLength,tableId);
			break;
		case DESC_LONG_TEXT:
			cell=new TextCell(null,content,TablePropertys.sLongDescLength,tableId);
			break;
		case DESC_TEXT:
			cell=new TextCell(null,content,TablePropertys.sCellDescLength,tableId);
			break;
		case DESC_SHORT_ANCHOR:	
			cell=new AnchorCell(content,TablePropertys.sShortDescLength,tableId);
			break;
		case DESC_LONG_ANCHOR:	
			cell=new AnchorCell(content,TablePropertys.sLongDescLength,tableId);	
		case DESC_ANCHOR:
			cell=new AnchorCell(content,TablePropertys.sCellDescLength,tableId);
			break;
		case BUTTON:
			cell=new ButtonCell(content);
			break;
		case CHECKBOX:
			cell=new CheckBoxCell(colName,content,propertys.getSHomeUrl(),null);
			break;
		case RADIO:
			cell = new RadioCell(colName,content,propertys.getSHomeUrl(),null);
			break;
		case INPUT_TEXT:
			cell = new InputCell(colName,colName,content,20);
			break;
		}
		tableCell=cell.get();
		_getBind(rowID, colName, tableCell);
		if(maxColWidth[col]<cell.getLength()+2){//计算最大宽度,2为表格单元格边框宽度
			maxColWidth[col]=cell.getLength()+2;
		}
		return tableCell;
	}

	/**
	 *  获取需要剔除重复列的列内容
	 */
	private String _disContent(String content,
			String colName) throws ErrorMessage{
		//获取当前列是否不显示重复数据
		boolean displayRepeat = 
			this.propertys.getDisRepeat(colName);
		if(!displayRepeat){//直接返回
			return content;
		}

		String preColContent = this.colContent.getByKey(colName);//获取列旧内容
		//如果未设置列内容容器,设置当前列内容为列比较器内容
		if(preColContent == null){
			this.colContent.put(colName, content);
			return content;
		}
		//比较当前列内容与旧内容
		if(preColContent.equals(content)){//返回空
			return "";
		}else{//设置列比较器的内容为当前列内容
			this.colContent.put(colName, content);
			return content;
		}
	}

	/**
	 * 设置描述字段 如果表格宽度为外部传入宽度,并且外部传入宽度大于表格宽度时
	 * 获取每列是否为描述列,如果是描述列,并且表格列不是外部传入,遍历数据集,根据当前列的最大宽度生成列单元格
	 * @return
	 * @throws ErrorMessage 
	 */
	private void _putDescCellAtOutWith(int colIndex,int colWidth) throws ErrorMessage{
		String colName = null;
		String content = null;
		String rowID=null;
		HtmlWindow cell=null;
		int rowIndex = 1;
		colName=propertys.getColName(colIndex);
		rowID=new ElementID(tableId,rowIndex).toString();
		data.beforeFirst();
		while(data.next()){//遍历数据集,根据当前列的最大宽度生成列单元格
			content = data.getString(colName);
			cell = new TextCell(null,content,TOOLS.intToString(colWidth),tableId).get();
			_getBind(rowID, colName, cell);
			table.replaceCol(cell, rowIndex++,colIndex);
		}
	}

	/**
	 * 根据绑定器生成单元格
	 * @param col 列号
	 * @param row     行号
	 * @param content 列内容
	 * @param rowID   单元格ID
	 * @throws ErrorMessage
	 */
	private HtmlWindow _getExtentTableCell(int row,int col,String rowID) throws ErrorMessage{
		HtmlWindow tableCell=null;
		String colName=propertys.getColName(col);
		Cell cell=null;

		HtmlWindow[] extendCell=null;
		if(propertys.isExtent(colName)){
			extendCell=_extentCol(colName, rowID,keyValue);
		}

		/**2 根据字段类型创建表格单元格对象，放入单元格 */
		switch (propertys.getTableColType(col)) {
		case NAME_TEXT: 
		case DESC_SHORT_TEXT:
		case DESC_TEXT:
		case DESC_LONG_TEXT:
			cell=new TextCell(); 
			break;
		case NAME_ANCHOR:
		case DESC_SHORT_ANCHOR:	
		case DESC_ANCHOR:
		case DESC_LONG_ANCHOR:
			cell=new AnchorCell(); 
			break;
		case BUTTON:
			cell=new ButtonCell(); 
			break;
		case CHECKBOX:
			cell=new CheckBoxCell();
			break;
		case INPUT_TEXT:
			cell = new InputCell();
			break;
		case RADIO:
			cell = new RadioCell();
			break;
		}
		if(extendCell!=null){
			cell.put(extendCell);
		}
		tableCell=cell.get();
		if(maxColWidth[col]<cell.getLength()+2){//计算最大宽度,2为表格单元格边框宽度
			maxColWidth[col]=cell.getLength()+2;
		}
		return tableCell;
	}

	/**
	 *  获取为外部传入或者用外部传入回调器生成的单元格内容
	 * @param colName 列名称
	 * @param rowID   单元格ID
	 */
	private HtmlWindow[] _extentCol(String colName,String rowID,String keyValue) throws ErrorMessage{
		HtmlWindow[] cell=null;
		//获取生成单元格内容的回调器
		CallBack callBack=propertys.getCallBack(colName);
		if(callBack!=null){//如果存在回调器,调用回调器生成单元格内容
			cell=callBack.getGroup(data, propertys.getSHomeUrl(), propertys.getUser());
		}else{//如果不存在回调器,直接获取单元格内容
			cell = this.copyExtentCol(colName);
		}
		if(cell==null){//如果未能获取单元格内容抛出异常
			throw new ErrorMessage("Col "+colName+" is not an outside cell or a callback cell in FlowTable!");
		}
		//绑定单元格事件
		_getBind(rowID, colName ,cell);
		return cell;
	}

	/**
	 *  单元格内容为外部传入时,拷贝外部传入对象为当前单元格内容
	 * @throws ErrorMessage
	 */
	private HtmlWindow[] copyExtentCol(String colName) throws ErrorMessage{
		//获取外部传入列内容
		HtmlWindow[] extents = this.propertys.getExtentColumn(colName);
		if(extents==null || extents.length<1){
			return null;
		}
		//拷贝当前列内容
		HtmlWindow [] copyExtents = new HtmlWindow[extents.length];
		for(int i=0;i<extents.length;i++){
			copyExtents[i] = extents[i].copy();
		}
		return copyExtents;
	}

	/**
	 * 绑定单元格事件
	 * @param cellID  单元格ID
	 * @param colName 列名
	 * @param cell    单元格对象
	 * @throws ErrorMessage
	 */
	private void _getBind(String cellID,String colName,HtmlWindow... cell) throws ErrorMessage{
		ArrayList<Window_Event> events=null;
		events=propertys.getEvent(colName);
		if(events!=null){
			for(int i=0;i<events.size();i++){
				String eventAct = propertys.getEventAct(colName).get(i);
				if(cell!=null&&cell.length>i&&eventAct!=null){
					cell[i].bind(events.get(i),
							TableScript.getBindScript(propertys.getEventFunction(colName).get(i), cellID,
									eventAct,
									propertys.getEventTarget(colName).get(i),
									this.keyValue,
									propertys.getOtherParams(colName).get(i))
					);
				}
			}
		}
	}

	/**
	 * 设置大小<br>
	 * <li>如果外部传入宽度-17大于表格实际内容占用宽度，表格宽度等于外部传入宽度-17，
	 * 	调整表格父容器DIV的宽度为外部传入宽度，调整表格宽度为外部传入宽度-17
	 * <li>如果外部传入宽度小于于表格实际占用宽度+17，大于表格实际占用宽度，调整表格父容器DIV宽度为表格宽度+17
	 * <li>如果外部传入宽度小于表格宽度，调整父亲容器宽度为外部传入宽度
	 * @throws ErrorMessage 
	 */
	private void _setSize() throws ErrorMessage{
		if(!TOOLS.StringIsEmpty(this.sOutWidth)){
			int iOutWidth=TOOLS.stringToInt(this.sOutWidth)-17;
			if(iOutWidth>width){
				_generatorMaxColWidth(iOutWidth, width);
				this.width=iOutWidth;
				this.clientWidth=this.sOutWidth;
			}else if(iOutWidth+17> width){
				this.clientWidth = TOOLS.intToString(width+17);
			}else{
				this.clientWidth = this.sOutWidth;
			}
		}

		if(!TOOLS.StringIsEmpty(this.sOutHeight)){
			if(TOOLS.stringToDouble(this.sOutHeight)<this.height){
				this.clientHeight=this.sOutHeight;
			} 
		}
	}

	/**
	 * 调整列最大宽度，在表宽度为外面设置时外面传入的宽带大于表实际宽度时<br>
	 * 表格含有描述列时所有的扩展宽度加到描述列上
	 * 如果不含描述列扩展宽度由列按比例分配
	 * @throws ErrorMessage 
	 */
	private void _generatorMaxColWidth(int outWidth,int innerWidth) throws ErrorMessage{
		if(propertys.haveDescCol()){//如果表格含有描述列
			int unDescColWidth = 0;
			for(int i=0;i<maxColWidth.length;i++){//计算非描述列所占宽度
				if(!propertys.isDescCol(i)){
					unDescColWidth = unDescColWidth + maxColWidth[i];
				}
			}
			outWidth = outWidth - unDescColWidth;
			innerWidth = innerWidth - unDescColWidth;
			for(int i=0;i<maxColWidth.length;i++){//按比例扩展描述列宽度，重新生成描述列内容
				if(propertys.isDescCol(i)){
					maxColWidth[i] = (int)(maxColWidth[i]*((double)outWidth/innerWidth));
					_putDescCellAtOutWith(i, maxColWidth[i]);
				}
			}
		}else{//如果不含描述列，所有列平均分配多余宽度
			for(int i=0;i<maxColWidth.length;i++){
				maxColWidth[i]=(int)(maxColWidth[i]*((double)outWidth/innerWidth));
			}
		}
	}

	/**
	 * 设置表格页面模式(单页模式 or 分页模式)
	 */
	private void _setPageProperty(){
		//当前表格绑定记录集为空,表格为单页模式
		if(this.result ==null)return;
		//获取当前记录集分页信息
		this.pageInfo = result.getPaging();
		//当前记录集无分页信息或者记录集为1页,表格为单页模式
		if(pageInfo == null || pageInfo.getTotal()<=1)return; 
		//设置当前表格为分页模式
		this.viewModel = Flow_Table_View_Model.Multi_Page; 
	}

	/**
	 * 计算表格宽度和高度  
	 */
	private void _generatorTableWidth() throws ErrorMessage{

		if(data!=null && !data.isNull()){
			/** 设置列宽度 */
			for(int i=0;i<propertys.getColNumber();i++){
				table.setColWidth(TOOLS.intToString(maxColWidth[i]), 0, i);
			}
		}

		/** 设置表格宽度 */
		table.setWidth(TOOLS.intToString(width));

		if(clientWidth!=null){
			table.setClientWidth(clientWidth);
		}else{
			table.setClientWidth(TOOLS.intToString(width+17));
		}
	}

	/**
	 *  放入附加元素
	 * @throws ErrorMessage 
	 */
	private void _setAddElements() throws ErrorMessage{
		for(Html ae: this.addElements){
			this.table.putExtend(ae);
		}
	}

	/**
	 * 初始化列标题 
	 * @throws ErrorMessage
	 */
	private synchronized void _initTitle() throws ErrorMessage{
		ThCell th=null;
		int i=0;
		for(i=0;i<propertys.getColNumber();i++){
			th=new ThCell(propertys.getTableColTitle(i));
			maxColWidth[i]=th.getLength();
			table.put(th.get(), 0, i,Table.Table_Cell_Type.TH);
		}
		this.height = this.height + TITLE_ROW_HEIGHT;
	}

	/**
	 * 计算表格高度 
	 */
	private synchronized void _getTableHeight(){
		this.height=this.height+PER_ROW_HEIGHT;
	}

	/**
	 * 计算表格宽度
	 */
	private void _getTableWidth(){
		width=0;
		for(int i=0;i<maxColWidth.length;i++){
			width=width+maxColWidth[i];
		}
	}

	/**
	 * 根据主键值，生成指定行的主键input
	 * @param row 行
	 * @param keyValue 主键值
	 */
	private Html _getRowHiddenKey(String rowID,String keyValue){
		HtmlValue hiddenKey=new HtmlValue(rowID+"r",mainKey,keyValue);
		return hiddenKey;
	}
}
